package org.yunai.yfserver.util;

import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.yunai.yfserver.common.LoggerFactory;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * {@link java.util.concurrent.ExecutorService}的工具集
 * User: yunai
 * Date: 13-4-28
 * Time: 上午10:55
 */
public class ExecutorUtils {

    private static final Logger LOGGER_SERVER = LoggerFactory.getLogger(LoggerFactory.Logger.server, ExecutorUtils.class);

    /**
     * 默认的{@link ExecutorService}关闭前等待其中的任务结束的时间:5分钟
     */
    private static final int DEFAULT_AWAIT_TERMINATE_MINUTES = 2;

    /**
     * 默认关闭{@link ExecutorService}<br />
     * 在指定的时间内{@link #DEFAULT_AWAIT_TERMINATE_MINUTES}等待<code>executorService</code>中已经开始的任务尽量结束.<br />
     * 此实现参照{@link ExecutorService}注释中的 <code>shutdownAndAwaitTermination</code>策略
     *
     * @param pool ExecutorService
     * @return 返回停止后任然未被开始执行的任务
     */
    public static List<Runnable> shutdownAndAwaitTermination(final ExecutorService pool) {
        return shutdownAndAwaitTermination(pool, DEFAULT_AWAIT_TERMINATE_MINUTES, TimeUnit.MINUTES);
    }

    /**
     * 关闭{@link ExecutorService}<br />
     * 在指定的时间内<code>awaitTerminateTimeout</code>等待<code>executorService</code>中已经开始的任务尽量结束.<br />
     * 此实现参照{@link ExecutorService}注释中的 <code>shutdownAndAwaitTermination</code>策略
     *
     * @param pool                  ExecutorService
     * @param awaitTerminateTimeout 等待停止时间
     * @param timeUnit              等待停止时间单位
     * @return 返回停止后任然未被开始执行的任务
     */
    public static List<Runnable> shutdownAndAwaitTermination(final ExecutorService pool,
                                                             final long awaitTerminateTimeout, final TimeUnit timeUnit) {
        List<Runnable> leftRunnable = null;
        pool.shutdown(); // Disable new tasks from being submitted
        try {
            // Wait a while for existing tasks to terminate
            boolean terminateResult = pool.awaitTermination(awaitTerminateTimeout, timeUnit);
            LOGGER_SERVER.info("[shutdownAndAwaitTermination] [{} shutdown {}].", pool, terminateResult ? "success" : "fail");
            // shutdown如果失败，进行shutdownNot操作
            if (!terminateResult) {
                leftRunnable = pool.shutdownNow();
                if (leftRunnable != null && leftRunnable.size() > 0) {
                    for (Runnable runnable : leftRunnable) {
                        LOGGER_SERVER.info("[shutdownAndAwaitTermination] [{} shutdownNow runnable {}].", pool, runnable);
                    }
                }
                // Wait a while for tasks to respond to being cancelled
                terminateResult = pool.awaitTermination(awaitTerminateTimeout, TimeUnit.SECONDS);
                LOGGER_SERVER.info("[shutdownAndAwaitTermination] [{} shutdownNow {}].", pool, terminateResult ? "success" : "fail");
            }
        } catch (InterruptedException ie) {
            LOGGER_SERVER.error("[shutdownAndAwaitTermination] [{} shutdown interrupted] [error:{}].", pool, ExceptionUtils.getStackTrace(ie));
            leftRunnable = pool.shutdownNow();
            if (leftRunnable != null && leftRunnable.size() > 0) {
                for (Runnable runnable : leftRunnable) {
                    LOGGER_SERVER.error("[shutdownAndAwaitTermination] [{} shutdown interrupted runnable {}].", pool, runnable);
                }
            }
            Thread.currentThread().interrupt();
        }
        return leftRunnable;
    }
}
